
	.386
if ?FLAT
	.MODEL FLAT, stdcall
else
	.MODEL SMALL, stdcall
endif
	option proc:private
	option casemap:none

	include winbase.inc
	include winioctl.inc
	include wincon.inc
	include macros.inc
	include dkrnl32.inc

?DOSWAIT	equ 0	;std=1, 1=wait in DOS (prevents thread switches!)

	.DATA

cntChars db 0

	.DATA?

buffer	db 256 dup (?)

	.CODE

if ?DPMI16	;for 16bit clients
simint21 proto
endif

SetLastError proto stdcall :dword

ReadFile proc public uses ebx esi edi handle:dword, pBuffer:dword,
		numBytes:dword, lpRead:ptr dword, lpOverlapped:ptr OVERLAPPED

local	ir:INPUT_RECORD

		@strace <"ReadFile(", handle, ", ", pBuffer, ", ", numBytes, ", ", lpRead, ", ", lpOverlapped, ") enter">
		mov eax,lpRead
		mov dword ptr [eax],0
		mov ebx,handle
		mov esi, lpOverlapped
if ?NONULLHDL
  ifdef _DEBUG
		and ebx, ebx
		jnz @F
		@strace <"ReadFile called with invalid handle 0">
		int 3
		mov ax,2
		jmp error
@@:
  endif
endif
		cmp ebx, 10000h
		ja isspecial
doread:
		mov edi,pBuffer
		mov ecx,numBytes
		.if (bx == 0000h)
			push ecx
			mov dl,0
			mov ax,4400h
			int 21h
			pop ecx
			test dl,80h
			jz isfile
if ?DOSWAIT
			test g_consoleflags, ENABLE_LINE_INPUT
			jz issingleinput
			mov edx,edi
			mov ah,3fh
if ?DPMI16
			call simint21
else
			int 21h
endif
			jc error
			push eax
			invoke FlushConsoleInputBuffer, handle
			pop eax
			jmp readdone
issingleinput:
endif
			call readconline
			jmp readdone
		.endif
isfile:
		.if (esi)
			push ecx
			invoke SetFilePointerEx, ebx, qword ptr [esi].OVERLAPPED.Offset_, NULL, FILE_BEGIN
			pop ecx
		.endif
		mov edx,edi
		mov ah,3fh
if ?DPMI16
		call simint21
else
		int 21h
endif
		jc error
		.if (esi)
			push eax
			mov [esi].OVERLAPPED.InternalHigh, eax
			invoke SetEvent, [esi].OVERLAPPED.hEvent
			pop eax
		.endif
readdone:
		mov ecx,lpRead
		mov [ecx],eax
done:
		mov eax,1
exit:
ifdef _DEBUG
		mov edx, lpRead
		mov edx, [edx]
		mov ecx, lpOverlapped
		jecxz @F
		mov ecx, dword ptr [ecx].OVERLAPPED.Offset_
@@:
endif
		@strace <"ReadFile(", handle, ", ", pBuffer, ", ", numBytes, ", ", lpRead, ", ", lpOverlapped, ")=", eax, " - bytes read=", edx, " ovofs=", ecx>
		ret
error:
		movzx eax,ax
		invoke SetLastError,eax
		xor eax, eax
		jmp exit
echochar:
		.if (g_consoleflags & ENABLE_ECHO_INPUT)
			push eax
			mov dl,al
			mov ah,2
			int 21h
			.if (al == 13)
				mov dl,10
				mov ah,2
				int 21h
			.endif
			pop eax
		.endif
		retn
		align 4

;--- special file handles
;--- ebx=handle
;--- esi=overlapped

isspecial:
		.if (ebx == -1)
		.elseif ([ebx].SYNCOBJECT.dwType == SYNCTYPE_PIPE)
			.while (1)
				push ebx
				mov ebx,[ebx].PIPE.dwfh
				xor edx,edx
				xor ecx,ecx
				mov ax,4201h			;get current file pos
				int 21h
				pop ebx
				jc error
				push dx
				push ax
				pop eax
				.break .if (eax != [ebx].PIPE.dwPos)
				invoke Sleep, 0
			.endw
			push esi
			xor esi, esi
			push eax
			call EnterSerialization
			invoke SetFilePointer, [ebx].PIPE.dwfh, [ebx].PIPE.dwPos, 0, 0
			push ebx
			mov	ebx,[ebx].PIPE.dwfh
			mov edx,pBuffer
			mov ecx,numBytes
			mov ah,3Fh
			int 21h
			pop	ebx
			.if (!CARRY?)
				add [ebx].PIPE.dwPos, eax
				mov esi, eax
			.endif
			pop eax
			invoke SetFilePointer, [ebx].PIPE.dwfh, eax, 0, 0
			call LeaveSerialization
			mov eax, esi
			pop esi
			jmp readdone
		.elseif ([ebx].SYNCOBJECT.dwType == SYNCTYPE_FILE)
			.if ([ebx].FILE.flags & (FF_DISK or FF_DRIVE or FF_DEVICE))
				invoke [ebx].FILE.pHandler, handle, FILE_READ_ACCESS, 0, 0,\
					pBuffer, numBytes, lpRead, esi
				jmp exit
			.endif
		.endif
		mov ax,6	;error "invalid handle"
		jmp error
		align 4

readconline:
		test g_consoleflags, ENABLE_LINE_INPUT
		jz @F
		mov edi, offset buffer
		mov ecx, 256
@@:
		mov esi, ecx
		mov eax, INFINITE
		.while (esi)
			.if (cntChars)
				mov al,[edi]
				dec cntChars
			.else
				invoke WaitForSingleObject, ebx, eax
				.if (!(g_consoleflags & ENABLE_LINE_INPUT))
					.break .if (eax != WAIT_OBJECT_0)
				.endif
@@:
				push 0
				invoke ReadConsoleInput, ebx, addr ir, 1, esp
				pop eax
				cmp ir.EventType, KEY_EVENT
				jnz @B
				cmp ir.Event.KeyEvent.bKeyDown, 0
				jz @B
				mov ax,ir.Event.KeyEvent.AsciiChar
				cmp al, 0
				jz @B
				.if (g_consoleflags & ENABLE_LINE_INPUT)
					.if ((al == 08) || (al == 7Fh))
						.if (esi < 256)
							inc esi
							dec edi
							call echochar
							mov al,' '
							call echochar
							mov al,8
							call echochar
						.endif
						jmp processed
					.endif
				.endif
				call echochar
			.endif
			stosb
			dec esi
			.if ((al == 13) && esi)
				mov al,10
				stosb
				dec esi
			.endif
processed:
			.if (g_consoleflags & ENABLE_LINE_INPUT)
				.if ((al == 13) || (al == 10))
					mov cntChars,0
					.break
				.endif
				mov eax, INFINITE
			.else
				mov eax, 0
			.endif
		.endw
		.if (g_consoleflags & ENABLE_LINE_INPUT)
			mov eax, edi
			mov esi, offset buffer
			sub eax, esi		;current bytes in buffer
			mov edi, pBuffer
			mov ecx, numBytes
			cmp eax, ecx
			jnc @F
			mov ecx, eax		;get the lower value in ecx
@@:
			sub eax, ecx
			rep movsb
			push edi
			mov edi, offset buffer
			mov ecx, eax
			mov cntChars, cl
			rep movsb
			pop edi
		.endif
		mov eax, edi
		sub eax, pBuffer
		mov ecx, numBytes
		cmp eax, ecx
		jbe @F
		mov eax, ecx
@@:
		retn
		align 4

ReadFile endp


	END
